#pragma once

#include <stdlib.h>
#include <cstdio>
#include <cassert>
#include <type_traits>


/**
 * Preprocessors
 */
#if __cplusplus >= 201103L
#define _TX_FINAL final
#define _TX_OVERRIDE override
#define _TX_NOEXCEPT noexcept
#else
#define _TX_FINAL
#define _TX_OVERRIDE
#define _TX_NOEXCEPT
#endif // __cplusplus >= 201103L

#ifdef TXDNN_BUILD_LIB
#if defined(_MSC_VER)
#define TXDNNAPI __declspec(dllexport)
#elif defined(__GNUC__)
#define TXDNNAPI __attribute__((__visibility__("default")))
#else
#define TXDNNAPI
#endif // _MSC_VER
#else
#define TXDNNAPI
#endif // TXDNN_BUILD_LIB

/**
 * Class helper macros
 */
#define NONCOPYABLE(Class)                  \
  Class(const Class&) = delete;             \
  Class& operator=(const Class&) = delete

#define NONMOVABLE(Class)                   \
  Class(Class&&) = delete;                  \
  Class& operator=(Class&&) = delete

#define NONCOPYABLE_AND_NONMOVABLE(Class)   \
  NONCOPYABLE(Class);                       \
  NONMOVABLE(Class)

#define DEFAULT_CTOR(Class)                 \
  Class() _TX_NOEXCEPT {}

#define CONSTEXPR_DEFAULT_CTOR(Class)       \
  constexpr Class() _TX_NOEXCEPT {}

#define VIRTUAL_DEFAULT_DTOR(Class) virtual ~Class() _TX_NOEXCEPT = default

#define ROOT_INTERFACE(Class)               \
protected:                                  \
  CONSTEXPR_DEFAULT_CTOR(Class)             \
                                            \
public:                                     \
  VIRTUAL_DEFAULT_DTOR(Class);              \
  NONCOPYABLE(Class)

#define ROOT_INTERFACE_PROTECTED_DTOR(Class)  \
protected:                                    \
  CONSTEXPR_DEFAULT_CTOR(Class)               \
  VIRTUAL_DEFAULT_DTOR(Class);                \
                                              \
public:                                       \
  NONCOPYABLE(Class)

#define COPY_CTOR(Class)                      \
  Class(const Class& rhs) _TX_NOEXCEPT { *this = rhs; }

#define MOVE_CTOR(Class)                      \
  Class(Class&& rhs) _TX_NOEXCEPT { *this = std::move(rhs); }

#define COPY_AND_MOVE_CTORS(Class)            \
  COPY_CTOR(Class)                            \
  MOVE_CTOR(Class)


/**
 * class common helper 
 */
namespace txdnn {

/**
 * NonCopyable
 */
class NonCopyable {
public:
  NonCopyable(const NonCopyable&) = delete;
  NonCopyable& operator=(const NonCopyable&) = delete;
protected:
  constexpr NonCopyable() _TX_NOEXCEPT = default;
  ~NonCopyable() _TX_NOEXCEPT = default;
};

} // namespace txdnn